#include "Task.hpp"
#include <iostream>
#include <string>
#include <vector>
#include <cstdlib>
#include <unistd.h>
#include <cassert>
#include <sys/stat.h>
#include <sys/wait.h>

using namespace std;

const int processnum = 5;
vector<task_t> tasks;

class channel
{
public:
	channel(int cmdfd, pid_t slaverid, const string &processname) : _cmdfd(cmdfd), _slaverid(slaverid), _processname(processname)
	{}

public:
	int _cmdfd;			 // 对应的写入描述符
	pid_t _slaverid;	 // 需要工作的进程的pid
	string _processname; // 对应名称
};

void slaver(){
	while(1){
		int cmdcode = 0;
		int n = read(0,&cmdcode,sizeof(int));
		if(n == 4){
			cout << "child say : I get a task->" << cmdcode << " my pid:" << getpid() << endl;
			if(cmdcode >= 0 && cmdcode < tasks.size()) tasks[cmdcode]();
		}
		if(n == 0) break;
		sleep(1);
	}
}

void Initprocesspool(vector<channel>* channels)
{
	vector<int> oldfd;
	for (int i = 0; i < processnum; i++)
	{
		int pipefd[2];
		int n = pipe(pipefd);
		assert(!n);
		(void)n;

		pid_t id = fork();
		if (id == 0)
		{
			cout << "fd " << getpid() << "close: ";
			for(auto& c : oldfd){
				cout << c << " ";
				close(c);
			}
			cout << endl;
			close(pipefd[1]);
			dup2(pipefd[0],0);
			slaver();
			cout << "quit slaver pid:" << getpid() << endl;
			exit(0);
		}
		close(pipefd[0]);
		string s = "process-" + to_string(i);
		channels->push_back(channel(pipefd[1], id, s));
		oldfd.push_back(pipefd[1]);
		sleep(1);
	}
}

void workprocess(const vector<channel>& channels){
	for(auto& iterator : channels){
		cout << iterator._processname << ":" << iterator._slaverid << "->" << iterator._cmdfd << endl;
	}
}

void ctrlslaver(vector<channel>& channels)
{
	int which = 0;
	int cnt = 5;
	while(cnt--)
	{
		int cmdcode = rand() % tasks.size();
	
		write(channels[which]._cmdfd,&cmdcode,sizeof(cmdcode));
		cout << "father say : " << cmdcode << " task already sendto " << channels[which]._slaverid << " its wfd:" 
		<< channels[which]._cmdfd << " name:" << channels[which]._processname << endl;

		which++;
		which %= channels.size();

		//sleep(1);
		
	}
}

void quitprocesss(vector<channel>& channels)
{
	for(auto& chan : channels) close(chan._cmdfd);

	for(auto& chan : channels) waitpid(chan._slaverid,NULL,0);
}

int main()
{
	vector<channel> channels;

	Loadtask(&tasks);

	Initprocesspool(&channels);

	workprocess(channels);

	srand(time(NULL)^2025^getpid());
	
	ctrlslaver(channels);

	sleep(5);

	quitprocesss(channels);

	sleep(5);
	// for(int i = 0;i <= 100; i++){
	// 	int cmdcode = rand() % tasks.size();
	// 	int process = rand() % channels.size();
	// 	write(channels[process]._cmdfd,&cmdcode,sizeof(cmdcode));
	// 	cout << "father say : " << cmdcode << " task already sendto " << channels[process]._slaverid << " its wfd:" 
	// 	<< channels[process]._cmdfd << " name:" << channels[process]._processname << endl;
	// 	sleep(1);
	// }

	//sleep(1000);
	return 0;
}